package bo.gustavo.scrapper.model;

import java.util.List;
import java.util.Properties;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;

import bo.gustavo.scrapper.util.DataBaseAccessType;

public class Persister {

	private static SessionFactory sessionFactory = null;

	private static ServiceRegistry serviceRegistry = null;

	private static final Persister instance = new Persister();

	private Persister() throws HibernateException {
		Configuration configuration = new Configuration();
		configuration.configure();

		Properties properties = configuration.getProperties();

		serviceRegistry = new ServiceRegistryBuilder().applySettings(properties).buildServiceRegistry();
		sessionFactory = configuration.buildSessionFactory(serviceRegistry);
	}

	public synchronized static Persister getInstance() {
		return instance;
	}

	public static SessionFactory getSessionFactory() {
		return sessionFactory;
	}

	/**
	 * Saves an object to disk
	 * */
	public synchronized void save(List<Object> obj) {
		Session session = null;
		Transaction tx = null;
		session = sessionFactory.getCurrentSession();
		tx = session.beginTransaction();
		for (Object object : obj) {
			session.save(object);
		}
		session.flush();
		session.close();
		tx.commit();
	}

	/**
	 * Saves an object to disk
	 * */
	public synchronized void save(Object obj) {
		Session session = null;
		Transaction tx = null;
		session = sessionFactory.getCurrentSession();
		tx = session.beginTransaction();
		session.save(obj);
		session.flush();
		session.close();
		tx.commit();
	}

	/**
	 * Deletes an object from the disk
	 * */
	public synchronized void delete(Object obj) {
		Session session = null;
		Transaction tx = null;
		session = sessionFactory.getCurrentSession();
		tx = session.beginTransaction();
		session.delete(obj);
		session.flush();
		session.close();
		tx.commit();
	}

	public synchronized void deleteList(String list) {
		Session session = null;
		Transaction tx = null;
		session = sessionFactory.getCurrentSession();
		tx = session.beginTransaction();
		String hql = "delete from Url url where url.id in (" + list + ")";
		Query query = session.createQuery(hql);
		query.executeUpdate();
		session.flush();
		session.close();
		tx.commit();
	}

	/**
	 * Returns the list of the Class received as parameter
	 * */
	public synchronized <T> List<T> list(Class<T> classToFind) {
		Session session = null;
		session = sessionFactory.openSession();
		List<T> result = session.createQuery("from " + classToFind.getSimpleName()).list();
		session.close();
		return result;
	}

	public synchronized <T> List<T> maskOperations(Class<T> classToFind, Object object, DataBaseAccessType type) {
		switch (type) {
		case SAVE:
			save(object);
			return null;

		case SAVE_LIST:
			List<Object> list = (List<Object>) object;
			save(list);
			return null;

		case DELETE:
			delete(object);
			return null;

		case DELETE_IN:
			deleteList((String) object);
			return null;

		case QUERY:
			return list(classToFind);

		}
		return null;
	}

}
